package com.defangit.production.orm;

import com.defangit.production.bll.OperatorBll;
import com.defangit.production.domain.Operator;
import laogen.hibernate.CommonFinder;
import laogen.hibernate.CommonService;
import laogen.hibernate.expanded.BitAnyMatchCriterion;
import laogen.lang.exception.ParameterNotValidException;
import laogen.util.StringUtil;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class OperatorService extends CommonService<Operator> implements OperatorBll {
    @Override
    public Operator addOperator(Operator operator) {
        if(operator==null) throw ParameterNotValidException.nullParameter("操作员");
        Operator target = findAll().name(operator.getOperatorName())
                .unique().get();
        if (target!=null) {
            throw ParameterNotValidException.constraintNotSatisfy("用户名称已被占用","名称被占,可添加前缀请重新起名");
        }
        add(operator);
        commitSession();
        return get(operator.getId()).orElseThrow(()->
            ParameterNotValidException.zeroIdOrEntityNonExist("操作员")
        );
    }


    @Override
    public Operator updateOperator(Operator operator) {
        if(operator==null) throw ParameterNotValidException.nullParameter("操作员");
        merge(operator);
        commitSession();
        return get(operator.getId()).orElseThrow(()->
                ParameterNotValidException.zeroIdOrEntityNonExist("操作员")
        );
    }

    public List<Operator> getOperators(List<Integer> ids) {
        if(ids.isEmpty()) return Collections.EMPTY_LIST;
        List<Operator> operators=detachedAll()
                .add(Restrictions.in("id",ids)).getExecutableCriteria(getSession())
                .list();
        return operators;
    }

    @Override
    public boolean deleteOperator(Operator operator) {
        return false;
    }

    @Override
    public OperatorFinder findAll() {
        return new OperatorFinderImp();
    }

    @Override
    public Operator login(String name, String pass) {
        Operator operator=(Operator)detachedAll().add(Restrictions.eq("operatorName",name))
                .getExecutableCriteria(getSession())
                .uniqueResult();
        return operator;
    }

    public class OperatorFinderImp extends CommonFinder<Operator> implements OperatorFinder {
        private DetachedCriteria criteria;
        OperatorFinderImp(){
            this.criteria=detachedAll();
        }
        @Override
        public Criteria getCriteria() {
            this.criteria = this.criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            return criteria.getExecutableCriteria(getSession())
                    .addOrder(Order.desc("id"));
        }

        @Override
        public DetachedCriteria getDetachedCriteria() {
            return criteria;
        }

        @Override
        public OperatorFinder loadStore() {
            this.criteria = this.criteria.setFetchMode("store", FetchMode.JOIN);
            return this;
        }

        @Override
        public OperatorFinder loadWorkShops() {
            this.criteria = this.criteria.setFetchMode("workShops", FetchMode.JOIN);
            return this;
        }

        @Override
        public OperatorFinder id(Integer id) {
            if (id == null || id == 0) return this;
            this.criteria = this.criteria.add(Restrictions.eq("id",id));
            return this;
        }

        @Override
        public OperatorFinder name(String name) {
            if (!StringUtil.notEmpty(name)){
               return this;
            }
            this.criteria = this.criteria.add(Restrictions.eq("name",name));
            return this;
        }

        @Override
        public OperatorFinder tag(Collection<Integer> tagId) {
            if (tagId==null||tagId.isEmpty()) return this;
            this.criteria.add(new BitAnyMatchCriterion("tags",tagId));
            return this;
        }

        @Override
        public OperatorFinder nameLike(String name) {
            if (!StringUtil.notEmpty(name)) return this;
            this.criteria.add(Restrictions.like("operatorName",name));
            return this;
        }

        @Deprecated
        @Override
        public OperatorFinder store(Integer storeId) {
            if (storeId==null||storeId==0) return this;
            this.criteria.add(Restrictions.eq("store.id",storeId));
            return this;
        }

        @Override
        public OperatorFinder workShopId(Integer workShop) {
            if (workShop==null||workShop == 0) return this;
            this.criteria.createAlias("workShops","workShop")
                    .add(Restrictions.eq("workShop.id",workShop));
            return this;
        }
    }

}
